package com.github.alenfive.rocketapi.function;


import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;

import java.util.*;
import java.util.concurrent.TimeUnit;

/**
 * redis类
 */
public class RedisFunction implements IFunction {
    @Autowired
    private StringRedisTemplate stringRedisTemplate;

    @Override
    public String getVarName() {
        return "redis";
    }

    /**
     * 字符串类型get
     *
     * @param key
     * @return
     */
    public Object get(String key) {
        return stringRedisTemplate.boundValueOps(key).get();
    }

    /**
     * 字符串普通set
     *
     * @param key
     * @param value
     */
    public void set(String key, Object value) {
        stringRedisTemplate.boundValueOps(key).set(value.toString());
    }

    public Boolean del(String key) {
        return stringRedisTemplate.delete(key);
    }

    /**
     * 设置key并设置失效时间
     *
     * @param key
     * @param value
     * @param ex    有效时间 秒
     */
    public void setex(String key, Object value, long ex) {
        stringRedisTemplate.opsForValue().set(key, value.toString(), ex, TimeUnit.SECONDS);
    }

    /**
     * 获取key剩余有效时间
     *
     * @param key
     */
    public Long ttl(String key) {
        return stringRedisTemplate.getExpire(key);
    }

    /**
     * 自增1
     *
     * @param key
     * @return
     */
    public Long incr(String key) {
        return stringRedisTemplate.opsForValue().increment(key);
    }

    /**
     * 自减1
     *
     * @param key
     * @return
     */
    public Long decr(String key) {
        return stringRedisTemplate.opsForValue().decrement(key);
    }

    /**
     * 自增指定数字
     *
     * @param key
     * @param increment
     * @return
     */
    public Long incrby(String key, long increment) {
        return stringRedisTemplate.opsForValue().increment(key, increment);
    }

    /**
     * 自减指定数字
     *
     * @param key
     * @param increment
     * @return
     */
    public Long decrby(String key, long increment) {
        return stringRedisTemplate.opsForValue().decrement(key, increment);
    }

    /**
     * 返回所有(一个或多个)给定 key 的值
     *
     * @param listkey
     * @return
     */
    public List<String> mget(Collection<String> listkey) {
        return stringRedisTemplate.opsForValue().multiGet(listkey);
    }

    /**
     * 同时设置一个或多个 key-value 对
     *
     * @param map
     */
    public void mset(Map<String, String> map) {
        stringRedisTemplate.opsForValue().multiSet(map);
    }

    /**
     * hash set 将哈希表 key 中的域 field 的值设为 value
     *
     * @param key
     * @param field
     * @param value
     */
    public void hset(String key, Object field, Object value) {
        stringRedisTemplate.opsForHash().put(key, field, value);
    }

    /**
     * hash get 返回哈希表 key 中给定域 field 的值。
     *
     * @param key
     * @param field
     * @return
     */
    public Object hget(String key, Object field) {
        return stringRedisTemplate.opsForHash().get(key, field);
    }

    /**
     * 同时将多个 field-value (域-值)对设置到哈希表 key 中
     *
     * @param key
     * @param map
     */
    public void hmset(String key, Map<String, String> map) {
        stringRedisTemplate.opsForHash().putAll(key, map);
    }

    /**
     * 返回哈希表 key 中，一个或多个给定域的值
     *
     * @param key
     * @param listfield
     * @return
     */
    public List<Object> hmget(String key, Collection<Object> listfield) {
        return stringRedisTemplate.opsForHash().multiGet(key, listfield);
    }

    /**
     * hash increby 为哈希表 key 中的域 field 的值加上增量 increment
     *
     * @param key
     * @param field
     * @param increment
     * @return
     */
    public long hincrby(String key, Object field, long increment) {
        return stringRedisTemplate.opsForHash().increment(key, field, increment);
    }

    /**
     * hash 删除
     *
     * @param key
     * @param field
     * @return
     */
    public long hdel(String key, Object field) {
        return stringRedisTemplate.opsForHash().delete(key, field);
    }

    /**
     * hash exists
     *
     * @param key
     * @param field
     * @return
     */
    public boolean hexists(String key, Object field) {
        return stringRedisTemplate.opsForHash().hasKey(key, field);
    }

    /**
     * hash hlen 返回哈希表 key 中域的数量
     *
     * @param key
     * @return
     */
    public Long hlen(String key) {
        return stringRedisTemplate.opsForHash().size(key);
    }


    /**
     * list lpush 将一个或多个值 value 插入到列表 key 的表头
     *
     * @param key
     * @param value
     */
    public void lpush(String key, String value) {
        stringRedisTemplate.opsForList().leftPush(key, value);
    }

    /**
     * list 将一个或多个值 value 插入到列表 key 的表尾(最右边)
     *
     * @param key
     * @param value
     */
    public void rpush(String key, String value) {
        stringRedisTemplate.opsForList().rightPush(key, value);
    }

    /**
     * 将列表 key 下标为 index 的元素的值设置为 value
     *
     * @param key
     * @param index
     * @param value
     */
    public void lset(String key, long index, String value) {
        stringRedisTemplate.opsForList().set(key, index, value);
    }

    /**
     * 移除并返回列表 key 的头元素
     *
     * @param key
     * @return
     */
    public String lpop(String key) {
        return stringRedisTemplate.opsForList().leftPop(key);
    }

    /**
     * 移除并返回列表 key 的尾元素
     *
     * @param key
     * @return
     */
    public String rpop(String key) {
        return stringRedisTemplate.opsForList().rightPop(key);
    }

    /**
     * 根据参数 count 的值，移除列表中与参数 value 相等的元素
     *
     * @param key
     * @param count
     * @param value
     * @return
     */
    public Long lrem(String key, long count, Object value) {
        return stringRedisTemplate.opsForList().remove(key, count, value);
    }

    /**
     * 返回列表 key 的长度
     *
     * @param key
     * @return
     */
    public Long llen(String key) {
        return stringRedisTemplate.opsForList().size(key);
    }

    /**
     * 返回列表 key 中指定区间内的元素，区间以偏移量 start 和 stop 指定
     *
     * @param key
     * @param start
     * @param end
     * @return
     */
    public List<String> lrange(String key, long start, long end) {
        return stringRedisTemplate.opsForList().range(key, start, end);
    }

    /**
     * 返回列表 key 中，下标为 index 的元素
     *
     * @param key
     * @param index
     * @return
     */
    public String lindex(String key, long index) {
        return stringRedisTemplate.opsForList().index(key, index);
    }

    /**
     * 将一个或多个 member 元素加入到集合 key 当中，已经存在于集合的 member 元素将被忽略
     *
     * @param key
     * @param values
     */
    public void sadd(String key, String... values) {
        stringRedisTemplate.opsForSet().add(key, values);
    }

    /**
     * 返回集合 key 的基数(集合中元素的数量)。
     *
     * @param key
     * @return
     */
    public Long scard(String key) {
        return stringRedisTemplate.opsForSet().size(key);
    }

    /**
     * 返回一个集合的全部成员，该集合是所有给定集合之间的差集
     *
     * @param key1
     * @param key2
     * @return
     */
    public Set<String> sdiff(String key1, String key2) {
        return stringRedisTemplate.opsForSet().difference(key1, key2);
    }

    /**
     * 这个命令的作用和 SDIFF 类似，但它将结果保存到 destination 集合，而不是简单地返回结果集。
     *
     * @param key1
     * @param key2
     * @param key3
     * @return
     */
    public Long sdiffstore(String key1, String key2, String key3) {
        return stringRedisTemplate.opsForSet().differenceAndStore(key1, key2, key3);
    }

    /**
     * 返回一个集合的全部成员，该集合是所有给定集合的交集。
     *
     * @param key1
     * @param key2
     * @return
     */
    public Set<String> sinter(String key1, String key2) {
        return stringRedisTemplate.opsForSet().intersect(key1, key2);
    }

    /**
     * 这个命令类似于 SINTER 命令，但它将结果保存到 destination 集合，而不是简单地返回结果集。
     *
     * @param key1
     * @param key2
     * @param key3
     * @return
     */
    public Long sinterstore(String key1, String key2, String key3) {
        return stringRedisTemplate.opsForSet().intersectAndStore(key1, key2, key3);
    }

    /**
     * 判断 member 元素是否集合 key 的成员。
     *
     * @param key
     * @param value
     * @return
     */
    public boolean sismember(String key, Object value) {
        return stringRedisTemplate.opsForSet().isMember(key, value);
    }

    /**
     * 返回集合 key 中的所有成员
     *
     * @param key
     * @return
     */
    public Set<String> smembers(String key) {
        return stringRedisTemplate.opsForSet().members(key);
    }

    /**
     * 返回一个集合的全部成员，该集合是所有给定集合的并集。
     *
     * @param key1
     * @param key2
     * @return
     */
    public Set<String> sunion(String key1, String key2) {
        return stringRedisTemplate.opsForSet().union(key1, key2);
    }

    /**
     * 这个命令类似于 SUNION 命令，但它将结果保存到 destination 集合，而不是简单地返回结果集
     *
     * @param key1
     * @param key2
     * @param key3
     * @return
     */
    public Long sunionstore(String key1, String key2, String key3) {
        return stringRedisTemplate.opsForSet().unionAndStore(key1, key2, key3);
    }

    /**
     * 移除集合 key 中的一个或多个 member 元素，不存在的 member 元素会被忽略。
     *
     * @param key
     * @param values
     * @return
     */
    public Long srem(String key, Object... values) {
        return stringRedisTemplate.opsForSet().remove(key, values);
    }

    /**
     * 将 member 元素从 source 集合移动到 destination 集合
     *
     * @param sourcekey
     * @param targetkey
     * @param value
     * @return
     */
    public Boolean smove(String sourcekey, String targetkey, String value) {
        return stringRedisTemplate.opsForSet().move(sourcekey, value, targetkey);
    }

    /**
     * 移除并返回集合中的一个随机元素。
     *
     * @param key
     * @return
     */
    public String spop(String key) {
        return stringRedisTemplate.opsForSet().pop(key);
    }

    /**
     * 返回集合中的一个随机元素
     *
     * @param key
     * @return
     */
    public String srandmember(String key) {
        return stringRedisTemplate.opsForSet().randomMember(key);
    }

    /**
     * 将一个或多个 member 元素及其 score 值加入到有序集 key 当中
     *
     * @param key
     * @param score
     * @param value
     */
    public Boolean zadd(String key, double score, String value) {
        return stringRedisTemplate.opsForZSet().add(key, value, score);
    }

    /**
     * 返回有序集 key 中，成员 member 的 score 值
     *
     * @param key
     * @param value
     * @return
     */
    public Double zscore(String key, String value) {
        return stringRedisTemplate.opsForZSet().score(key, value);
    }

    /**
     * 为有序集 key 的成员 member 的 score 值加上增量 increment 。
     *
     * @param key
     * @param increment
     * @param value
     * @return
     */
    public Double zincrby(String key, double increment, String value) {
        return stringRedisTemplate.opsForZSet().incrementScore(key, value, increment);
    }

    /**
     * 返回有序集 key 的基数
     *
     * @param key
     * @return
     */
    public Long zcard(String key) {
        return stringRedisTemplate.opsForZSet().size(key);
    }

    /**
     * 返回有序集 key 中， score 值在 min 和 max 之间(默认包括 score 值等于 min 或 max )的成员的数量
     *
     * @param key
     * @param mincount
     * @param maxcount
     * @return
     */
    public Long zcount(String key, double mincount, double maxcount) {
        return stringRedisTemplate.opsForZSet().count(key, mincount, maxcount);
    }

    /**
     * 返回有序集 key 中，指定区间内的成员 其中成员的位置按 score 值递减(从小到大)来排列
     *
     * @param key
     * @param start
     * @param stop
     * @return
     */
    public Set<String> zrange(String key, long start, long stop) {
        return stringRedisTemplate.opsForZSet().range(key, start, stop);
    }

    /**
     * 返回有序集 key 中，所有 score 值介于 min 和 max 之间的成员 小到大排列
     *
     * @param key
     * @param minscore
     * @param maxscore
     * @return
     */
    public Set<String> zrangebyscore(String key, double minscore, double maxscore) {
        return stringRedisTemplate.opsForZSet().rangeByScore(key, minscore, maxscore);
    }

    /**
     * 返回有序集 key 中，指定区间内的成员 其中成员的位置按 score 值递减(从大到小)来排列
     *
     * @param key
     * @param start
     * @param stop
     * @return
     */
    public Set<String> zrevrange(String key, long start, long stop) {
        return stringRedisTemplate.opsForZSet().reverseRange(key, start, stop);
    }

    /**
     * 返回有序集 key 中，所有 score 值介于 min 和 max 之间的成员 大到小排列
     *
     * @param key
     * @param minscore
     * @param maxscore
     * @return
     */
    public Set<String> zrevrangebyscore(String key, double minscore, double maxscore) {
        return stringRedisTemplate.opsForZSet().reverseRangeByScore(key, minscore, maxscore);
    }

    /**
     * 返回有序集 key 中成员 member 的从小到大排名
     *
     * @param key
     * @param value
     * @return
     */
    public Long zrank(String key, Object value) {
        return stringRedisTemplate.opsForZSet().rank(key, value);
    }

    /**
     * 返回有序集 key 中成员 member 的从大到小排名
     *
     * @param key
     * @param value
     * @return
     */
    public Long zrevrank(String key, Object value) {
        return stringRedisTemplate.opsForZSet().reverseRank(key, value);
    }

    /**
     * 移除有序集 key 中的一个或多个成员，不存在的成员将被忽略
     *
     * @param key
     * @param values
     * @return
     */
    public Long zrem(String key, Object... values) {
        return stringRedisTemplate.opsForZSet().remove(key, values);
    }

    /**
     * 移除有序集 key 中，指定排名(rank)区间内的所有成员
     *
     * @param key
     * @param start
     * @param stop
     * @return
     */
    public Long zremrangebyrank(String key, long start, long stop) {
        return stringRedisTemplate.opsForZSet().removeRange(key, start, stop);
    }

    /**
     * 移除有序集 key 中，所有 score 值介于 min 和 max 之间(包括等于 min 或 max )的成员
     *
     * @param key
     * @param minscore
     * @param maxscore
     * @return
     */
    public Long zremrangebyscore(String key, double minscore, double maxscore) {
        return stringRedisTemplate.opsForZSet().removeRangeByScore(key, minscore, maxscore);
    }

}
